/*BUILDIO.C  by NeuroDynamX, Inc. Copyright 1991
  by Jixing Chen
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dir.h>
#include <dos.h>
#include <values.h>

#define FALSE 0
#define TRUE  !FALSE

main(int argc, char *argv[])
{
	FILE	*infpt, *outfpt;
	struct	ffblk	ffblk;
	char	*filenamept, filename[80], prob_dscrp[256];
	char	arb, arb_input[100], arb_output[100], ptnt[80], elmt[80];
	char	buf[5000], NOINPUT, SOMETHING;
	int	InNum, OutNum, TimeShift, length, abn_end, i, j, k;
	int	NumNrn;
        unsigned long int index=0L;
	int	form, rcd_length, in_field[100], out_field[100];
	int	maximum_in, maximum_out, in_jj, out_jj;
	float	input, output, input_buf[100], output_buf[100];

	/* If an incorrect command format is used, the program prompt
	user the expected command format.   */
	if (argc != 3) {
		printf("Command line syntax:\n");
		printf("	IOBUILD input_file_name output_file_name\n");
		exit(0);
	}

	/* Handle the proper openning of specified file 
	as input data file. */
	while ( findfirst(argv[1], &ffblk, 0) != 0 ){
		printf("File [%s] does not exist.\n", argv[1]);
		printf("Please input the input_file_name again \n>>> ");
		scanf("%s", argv[1]);
	}
	infpt = fopen(argv[1], "r");

	/* Handle the proper openning of specified file as output data
	file. */
	filenamept = filename;
	do {
	   length = 1;
	   while ( (findfirst(argv[2], &ffblk, 0) == 0) && (length != 0) ){
		printf("File [%s] exists.\n", argv[2]);
		printf("Please input the output_file_name again,\n");
		printf("\tRETURN automatically overwrites the existing file \n>>> ");
		scanf("%[^\n]", filenamept);
		while( (*filenamept == '\t') || (*filenamept == ' ') )
			filenamept ++;
		fgetchar();
		if ( (length = strlen(filenamept)) > 0 )
			sscanf(filenamept, "%[^\t ]", argv[2]);
	   }
	}
	while( (outfpt = fopen(argv[2], "w")) == NULL );

	/* Get the input data format. */
	NOINPUT = TRUE;
	while(NOINPUT) {
	   printf("Please specify the format of your ASCII data file:\n");
	   printf("\t(1) Inputs followed by outputs;\n");
	   printf("\t(2) Input and output locations in a \n\t    record to be specified;\n");
	   printf("\t(3) Outputs are delayed inputs (TrueTime sequence problem).\n");
           printf(">>> ");
	   scanf("%d", &form);
	   getchar();
	   if( (form == 1) || (form == 2) || (form == 3) )
		NOINPUT = FALSE;
	   else
		printf("This format specification is not defined!\n");
	}

	/* Get the problem description. */
	printf("Input one line description of the problem:\n>>> ");
	gets(prob_dscrp);
	fprintf(outfpt, "%c %s\n", '*', prob_dscrp);

	/* Get information for each input data format. */
	switch(form) {
	   case 1:
		/* Get the number of inputs in each pair. */
		NOINPUT = TRUE;
		while(NOINPUT) {
		   printf("Specify the number of inputs >>> ");
		   scanf("%d", &InNum);
		   getchar();
		   if (InNum < 1)
			printf("The number of inputs must be 1 or greater.\n");
		   else{
			NOINPUT = FALSE;
			fprintf(outfpt, "%s\n", "* Number of inputs:");
			fprintf(outfpt, "%d\n", InNum);
		   }
		}
		/* Get the number of outputs in each pair. */
		NOINPUT = TRUE;
		while(NOINPUT) {
		   printf("Specify the number of outputs >>> ");
		   scanf("%d", &OutNum);
		   getchar();
		   if (OutNum < 1)
			printf("The number of outputs must be 1 or greater.\n");
		   else{
			NOINPUT = FALSE;
			fprintf(outfpt, "%s\n", "* Number of outputs:");
			fprintf(outfpt, "%d\n\n", OutNum);
		   }
		}
		break;
	   case 2:
		/* Get positions in each record for inputs. */
		printf("Specify the length of a record >>> ");
		scanf("%d", &rcd_length);
		getchar();
		NOINPUT = TRUE;
		while(NOINPUT){
		   printf("Specify the fields in a record as inputs,\n");
		   printf("e.g. 1  8  3 9 (0 represents the first field);\n>>> ");
		   InNum = 0;
		   SOMETHING = TRUE;
		   while(SOMETHING){
			scanf("%d", &in_field[InNum]);
			InNum ++;
			if(getchar() == '\n')
			   SOMETHING = FALSE;
		   }
		   if(InNum<1)
			printf("The number of inputs must be 1 or greater.\n");
		   else {
			maximum_in = in_field[0];
			for(i=0;i<InNum;i++)
			   if(in_field[i]>maximum_in)
				maximum_in = in_field[i];
			if(maximum_in < rcd_length){
			   NOINPUT = FALSE;
			   fprintf(outfpt, "%s\n", "* Number of inputs:");
			   fprintf(outfpt, "%d\n", InNum);
			}
			else
			   printf("Specified input fields do not match the record.\n");
		   }
		}
		/* Get positions in each record for outputs. */
		NOINPUT = TRUE;
		while(NOINPUT){
		   printf("Specify the fields in a record as outputs,\n");
		   printf("e.g. 2  5  (0 represents the first field);\n>>> ");
		   OutNum = 0;
		   SOMETHING = TRUE;
		   while(SOMETHING){
			scanf("%d", &out_field[OutNum]);
			OutNum ++;
			if(getchar() == '\n')
			   SOMETHING = FALSE;
		   }
		   if(OutNum<1)
			printf("The number of outputs must be 1 or greater.\n");
		   else {
			maximum_out = out_field[0];
			for(i=0;i<OutNum;i++)
			   if(out_field[i]>maximum_out)
				maximum_out = out_field[i];
			if(maximum_out < rcd_length){
			   NOINPUT = FALSE;
			   fprintf(outfpt, "%s\n", "* Number of outputs:");
			   fprintf(outfpt, "%d\n\n", OutNum);
			}
			else
			   printf("Specified output fields do not match the record.\n");
		   }
		}
		break;
	   case 3:
		/* Get the length of a sequence. */
		printf("Specify the number of IO pairs per IO sequence >>> ");
		scanf("%d", &rcd_length);
		getchar();
		/* Get the number of inputs in each pair. */
		NOINPUT = TRUE;
		while(NOINPUT) {
		   printf("Specify the number of inputs in each IO pair >>> ");
		   scanf("%d", &InNum);
		   getchar();
		   if (InNum < 1)
			printf("The number of inputs must be 1 or greater.\n");
		   else{
			NOINPUT = FALSE;
			fprintf(outfpt, "%s\n", "* Number of inputs:");
			fprintf(outfpt, "%d\n", InNum);
		   }
		}
		/* Get the number of neurons in the network. */
		NOINPUT = TRUE;
		while(NOINPUT) {
		   printf("Specify the number of neurons in the TrueTime network >>> ");
		   scanf("%d", &NumNrn);
		   getchar();
		   if (NumNrn < 1)
			printf("The number of neurons must be 1 or greater.\n");
		   else{
			NOINPUT = FALSE;
		   }
		}
		/* Get the number of outputs in each pair. */
		NOINPUT = TRUE;
		while(NOINPUT) {
		   printf("Specify the number of outputs in each IO pair >>> ");
		   scanf("%d", &OutNum);
		   getchar();
		   if ( (OutNum < 1) || (OutNum > NumNrn) )
			printf("The number of outputs must be 1 or greater,\nand less than the neurons in the network.\n");
		   else{
			NOINPUT = FALSE;
			fprintf(outfpt, "%s\n", "* Number of outputs:");
			fprintf(outfpt, "%d\n\n", NumNrn);
		   }
		}
		/* Get the time-shift of input-output pair. */
		NOINPUT = TRUE;
		while(NOINPUT) {
		   printf("How many IO pairs into the future do you want to predict >>> ");
		   scanf("%d", &TimeShift);
		   getchar();
		   if ( (TimeShift < 1)
				|| ((TimeShift+InNum) >= rcd_length) )
			printf("The this must be 1 unit or greater,\n and does not exceed the end of the sequence.\n");
		   else{
			NOINPUT = FALSE;
		   }
		}
		break;
	}

	/* Get pattern descriptor and element descriptor. */
	printf("Input the IO sequence name >>> ");
	gets(ptnt);
	printf("Input the IO pair name >>> ");
	gets(elmt);

	/* Create io file for DYNA based on input data file. */
	switch(form) {
	   case 1:
		/* Create pairs of inputs and outputs. */
		while( feof(infpt) == 0 ) {
		   index ++;
		   printf("Records parsed: %lu\r",index);
		   fprintf(outfpt, "%s%lu\n", "* pair ", index);
		   fprintf(outfpt, "%c %s%lu\n", '@', ptnt, index);
		   fprintf(outfpt, "%c %s%lu\n", '#', elmt, index);
		   /* Get inputs from input data file for one pair and
		   output them to the io file. */
		   for ( i=0; i<InNum; i++){
			fetch(infpt, &input, &arb);
			if(arb == '%')
			   fprintf(outfpt, "%c        ", '%');
			else
			   fprintf(outfpt, "%f ", input);
		   }
		   /* Get outputs from input data file for one pair and
		   output them to the io file. */
		   for ( i=0; i<OutNum; i++){
			fetch(infpt, &output, &arb);
			if(arb == '%')
			   fprintf(outfpt, "%c        ", '%');
			else
			   fprintf(outfpt, "%f ", output);
		   }
		   fprintf(outfpt, "\n\n");
		   /* Check if input data file ends abruptly. */
		   if ( feof(infpt) != 0 ){
			clearerr(infpt);
			fclose(infpt);
			printf("\nThe input file ends abruptly! \nCheck data file [%s] please.\n", argv[1]);
                        printf("At least one record was found to be incomplete!\n");
                        fprintf(outfpt, "* At least one record was found to be incomplete in the input data file!\n");
			fprintf(outfpt, "* The End of I/O Data Patterns.\n");
			exit(0);
		   }

		   /* Clear the remains and check if the input data
		   file ends. */
		   NOINPUT = TRUE;
		   while( NOINPUT && (feof(infpt) == 0) ) {
			fscanf(infpt, "%*[^0-9%(-]");
			if ( fgetc(infpt) == '(' ){
			   fscanf(infpt, "%*[^)]");
			   fgetc(infpt);
			}
			else
			   NOINPUT = FALSE;
			if ( feof(infpt) != 0 ){
			   clearerr(infpt);
			   fclose(infpt);
			   fprintf(outfpt, "* The End of I/O Data Patterns.\n");
			   exit(0);
			}
			fseek(infpt, -1L, 1);
		   }
		}
		break;
	   case 2:
		/* Create pairs of inputs and outputs. */
		while( feof(infpt) == 0 ) {
		   index ++;
                   printf("Records parsed: %lu\r",index);
		   fprintf(outfpt, "%s%lu\n", "* pair ", index);
		   fprintf(outfpt, "%c %s%lu\n", '@', ptnt, index);
		   fprintf(outfpt, "%c %s%lu\n", '#', elmt, index);
		   in_jj=0;
		   out_jj=0;
		   /* Get inputs and outputs from input data file for
		   one pair. */
		   for ( i=0; i<rcd_length; i++){
			fetch(infpt, &input, &arb);
			for(j=0;j<InNum;j++)
			   if(in_field[j] == i){
				input_buf[in_jj]=input;
				arb_input[in_jj++]=arb;
			   }
			for(j=0;j<OutNum;j++)
			   if(out_field[j] == i){
				output_buf[out_jj]=input;
				arb_output[out_jj++]=arb;
			   }
		   }
		   /* Write the inputs and outputs to the io file. */
		   for(i=0;i<InNum;i++){
			if(arb_input[i] == '%')
			   fprintf(outfpt, "%c        ", '%');
			else
			   fprintf(outfpt, "%f ", input_buf[i]);
		   }
		   for(i=0;i<OutNum;i++){
			if(arb_output[i] == '%')
			   fprintf(outfpt, "%c        ", '%');
			else
			   fprintf(outfpt, "%f ", output_buf[i]);
		   }
		   fprintf(outfpt, "\n\n");
		   /* Check if input data file ends abruptly. */
		   if ( feof(infpt) != 0 ){
			clearerr(infpt);
			fclose(infpt);
                        printf("\nThe input file ends abruptly! \nCheck data file [%s] please.\n", argv[1]);
                        printf("At least one record was found to be incomplete!\n");
                        fprintf(outfpt, "* At least one record was found to be incomplete in the input data file!\n");
			fprintf(outfpt, "* The End of I/O Data Patterns.\n");
			exit(0);
		   }

		   /* Clear the remains and check if the input data
		   file ends. */
		   NOINPUT = TRUE;
		   while( NOINPUT && (feof(infpt) == 0) ) {
			fscanf(infpt, "%*[^0-9%(-]");
			if ( fgetc(infpt) == '(' ){
			   fscanf(infpt, "%*[^)]");
			   fgetc(infpt);
			}
			else
			   NOINPUT = FALSE;
			if ( feof(infpt) != 0 ){
			   clearerr(infpt);
			   fclose(infpt);
			   fprintf(outfpt, "* The End of I/O Data Patterns.\n");
			   exit(0);
			}
			fseek(infpt, -1L, 1);
		   }
		}
		break;
	   case 3:
		/* Create pairs of inputs and outputs. */
		while( feof(infpt) == 0 ) {
		   index ++;
                   printf("Sequences parsed: %lu\r",index);
		   fprintf(outfpt, "%s%lu\n", "* sequence ", index);
		   fprintf(outfpt, "%c %s%lu\n", '@', ptnt, index);
		   /* Get inputs and outputs from input data file for
		   one pair. */
		   for ( i=0; i<rcd_length; i++)
			fetch(infpt, &input_buf[i], &arb_input[i]);
		   for ( i=0; i<TimeShift+NumNrn; i++)
			arb_input[rcd_length+i] = '%';
		   /* Write the inputs and outputs to the io file. */
		   for ( k=0; k <= (rcd_length - InNum); k++){
		      fprintf(outfpt, "%c %s%d\n", '#', elmt, k+1);
		      for(i=0;i<InNum;i++){
			if(arb_input[k+i] == '%')
			   fprintf(outfpt, "%c        ", '%');
			else
			   fprintf(outfpt, "%f ", input_buf[k+i]);
		      }
		      for(i=0;i<OutNum;i++){
			if(arb_input[k+InNum-1+TimeShift+i] == '%')
			   fprintf(outfpt, "%c        ", '%');
			else
			   fprintf(outfpt, "%f ",
				input_buf[k+InNum-1+TimeShift+i]);
		      }
		      for ( i=0; i<NumNrn-OutNum; i++)
			   fprintf(outfpt, "%c        ", '%');
		      fprintf(outfpt, "\n\n");
		   }
		   /* Check if input data file ends abruptly. */
		   if ( feof(infpt) != 0 ){
			clearerr(infpt);
			fclose(infpt);
                        printf("\nThe input file ends abruptly! \nCheck data file [%s] please.\n", argv[1]);
                        printf("At least one record was found to be incomplete!\n");
                        fprintf(outfpt, "* At least one record was found to be incomplete in the input data file!\n");
			fprintf(outfpt, "* The End of I/O Data Patterns.\n");
			exit(0);
		   }

		   /* Clear the remains and check if the input data
		   file ends. */
		   NOINPUT = TRUE;
		   while( NOINPUT && (feof(infpt) == 0) ) {
			fscanf(infpt, "%*[^0-9%(-]");
			if ( fgetc(infpt) == '(' ){
			   fscanf(infpt, "%*[^)]");
			   fgetc(infpt);
			}
			else
			   NOINPUT = FALSE;
			if ( feof(infpt) != 0 ){
			   clearerr(infpt);
			   fclose(infpt);
			   fprintf(outfpt, "* The End of I/O Data Patterns.\n");
			   exit(0);
			}
			fseek(infpt, -1L, 1);
		   }
		}
		break;
	}
}


fetch(FILE *infpt, float *input, char *arb)
{
	char	NOINPUT, ch;

	/* Pick the number from among commonts in the
	input data file.  */
	*arb = ' ';
	NOINPUT = TRUE;
	while( NOINPUT && (feof(infpt) == 0) ) {
	   fscanf(infpt, "%*[^0-9%(-]");
	   if ( (ch=fgetc(infpt)) != EOF ){
	   	if ( ch == '(' ){
		   fscanf(infpt, "%*[^)]");
		   fgetc(infpt);
		}
	   	else {
		   if(ch == '%'){
			*arb = '%';
		   }
		   else{
			fseek(infpt, -1L, 1);
	   		fscanf(infpt, "%f", input);
		   }
		   NOINPUT = FALSE;
	   	}
	     }
	}
}
